﻿using System.Data.Entity.Core;
using KPIS.GERP.Models;
using KPIS.GERP.Models.ICM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Web.Mvc;
using System.Data.Entity;
using System.Linq.Dynamic;
using KPIS.GERP.Models.SYS;
using System.Data;
using KPIS.GERP.Models.Class;

namespace KPIS.GERP.WCF.GIMS
{
    [ServiceContract]
    public interface IPurchaseOrderService
    {
        [OperationContract]
        string GenNewPo(int year, int month);

        [OperationContract]
        IEnumerable<PurchaseOrder> Select(PurchaseOrder filter = null, List<string> includeSubObjectString = null);

        [OperationContract]
        List<SelectListItem> SelectList(PurchaseOrder criteriaModel = null);

        [OperationContract]
        int Insert(PurchaseOrder model, int createByUserId);

        [OperationContract]
        void Update(PurchaseOrder model, int updateByUserId);

        [OperationContract]
        void Delete(int Id, int deleteByUserId);

        #region [penalty]

        [OperationContract]
        IEnumerable<PurchaseOrderPenalty> SelectPoPenalty(PurchaseOrderPenalty filter = null,
            List<string> includeSubObjectString = null);

        [OperationContract]
        int InsertPoPenalty(PurchaseOrderPenalty model, int createByUserId);

        [OperationContract]
        void UpdatePoPenalty(PurchaseOrderPenalty model, int updateByUserId);

        [OperationContract]
        int? DeletePoPenalty(int Id, int deleteByUserId);

        #endregion [penalty]

        #region [Installment]

        [OperationContract]
        IEnumerable<PurchaseOrderInstallment> SelectPoInstallment(PurchaseOrderInstallment filter = null,
            List<string> includeSubObjectString = null);

        [OperationContract]
        int InsertPoInstallment(PurchaseOrderInstallment model, int createByUserId);

        [OperationContract]
        void UpdatePoInstallment(PurchaseOrderInstallment model, int updateByUserId);

        [OperationContract]
        int DeletePoInstallment(int Id, int deleteByUserId);

        #endregion [Installment]

        #region [InstallmentItem]

        [OperationContract]
        IEnumerable<PurchaseOrderInstallmentItem> SelectPoInstallmentItem(PurchaseOrderInstallmentItem filter = null,
            List<string> includeSubObjectString = null);

        [OperationContract]
        int InsertPoInstallmentItem(PurchaseOrderInstallmentItem model, int createByUserId);

        [OperationContract]
        void UpdatePoInstallmentItem(PurchaseOrderInstallmentItem model, int updateByUserId);

        [OperationContract]
        int DeletePoInstallmentItem(int Id, int deleteByUserId);

        [OperationContract]
        string[] ContactPo(int PoId);

        [OperationContract]
        List<string[]> TotalNetAmountPoItem(int PoId);

        [OperationContract]
        string[] CollateralPo(int PoId);

        [OperationContract]
        string ThaiBaht(string txt);

        [OperationContract]
        string[] PositionNamePo(int PoId);

        [OperationContract]
        List<Dictionary<string, string>> PoItems(int PoId);

        #endregion [InstallmentItem]
    }

    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "PurchaseOrderService" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select PurchaseOrderService.svc or PurchaseOrderService.svc.cs at the Solution Explorer and start debugging.
    public class PurchaseOrderService : IPurchaseOrderService
    {

        public string GenNewPo(int year, int month)
        {
            try
            {
                year = DateTime.Now.Year;
                month = DateTime.Now.Month;

                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseOrder> query = context.PurchaseOrders;

                    int cnt =
                        query.Where(a => a.CreatedWhen.Value.Year == year && a.CreatedWhen.Value.Month == month)
                            .OrderByDescending(a => a.PoId)
                            .Count();

                    string data = "PO-" + year.ToString("0000") + month.ToString("00") + "-" + (cnt + 1).ToString("000");
                    return data;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IEnumerable<PurchaseOrder> Select(PurchaseOrder criteriaModel = null,
            List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseOrder> query = context.PurchaseOrders;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query,
                            (current, includePath) => current.Include(includePath));
                    }

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(
                            KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    var x = query.ToList();
                    return x;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public List<SelectListItem> SelectList(PurchaseOrder criteriaModel = null)
        {
            var list = new List<SelectListItem>();

            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseOrder> query = context.PurchaseOrders;

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(
                            KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    var x = query.ToList();
                    foreach (var PurchaseOrder in x)
                    {
                        var item = new SelectListItem {Text = PurchaseOrder.Code, Value = PurchaseOrder.PoId.ToString()};
                        list.Add(item);
                    }
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return list;
            //throw new NotImplementedException();
        }

        public int Insert(PurchaseOrder model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    model.RecordStatus = RecordStatus.WaitStatus;
                    model.CreatedBy = createByUserId;
                    model.CreatedWhen = DateTime.Now;
                    model.Code = CodeGenerate.GetNextCode(CodeGenerate.TransectionType.PurchaseOrder, "");
                    context.PurchaseOrders.Add(model);
                    context.SaveChanges();

                    return model.PoId;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public void Update(PurchaseOrder model, int updateByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public void Delete(int Id, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.PurchaseOrders.Find(Id);
                    if (modelToDelete == null) return;

                    context.Entry(modelToDelete).State = EntityState.Modified;
                    modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    modelToDelete.UpdatedBy = deleteByUserId;
                    modelToDelete.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        #region [penalty] 

        public IEnumerable<PurchaseOrderPenalty> SelectPoPenalty(PurchaseOrderPenalty criteriaModel = null,
            List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseOrderPenalty> query = context.PurchaseorderPenalties;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query,
                            (current, includePath) => current.Include(includePath));
                    }

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(
                            KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    var x = query.ToList();
                    return x;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public int InsertPoPenalty(PurchaseOrderPenalty model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    // model.re = RecordStatus.WaitStatus;
                    model.CreatedBy = createByUserId;
                    model.CreatedWhen = DateTime.Now;
                    context.PurchaseorderPenalties.Add(model);
                    context.SaveChanges();

                    return model.PoPenId;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            // throw new NotImplementedException();
        }

        public void UpdatePoPenalty(PurchaseOrderPenalty model, int updateByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public int? DeletePoPenalty(int Id, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.PurchaseorderPenalties.Find(Id);
                    int? poid = modelToDelete.PoId;
                    if (modelToDelete == null) return 0;

                    // context.Entry(modelToDelete).State = EntityState.Deleted;
                    context.PurchaseorderPenalties.Remove(modelToDelete);
                    //modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    //modelToDelete.UpdatedBy = deleteByUserId;
                    //modelToDelete.UpdatedWhen = DateTime.Now;                    
                    context.SaveChanges();
                    return poid;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        #endregion [penalty]

        #region [InstallmentItem]

        public IEnumerable<PurchaseOrderInstallment> SelectPoInstallment(PurchaseOrderInstallment filter = null,
            List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseOrderInstallment> query = context.PurchaseOrderInstallments;
                    PurchaseOrderInstallmentItem[] queryItemAll = context.PurchaseOrderInstallmentItems.ToArray();

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query,
                            (current, includePath) => current.Include(includePath));
                    }

                    if (filter != null)
                    {
                        object[] param;
                        query = query.Where(Utility.GenerateWhereString(filter, out param), param);
                    }

                    var x = query.ToList();

                    foreach (var model in x)
                    {
                        var TotalAmount =
                            queryItemAll.Where(o => o.PoInstallId == model.PoInstallId).Sum(m => m.NetAmount ?? 0);
                        model.TotalAmount = (decimal) TotalAmount;
                    }

                    return x;
                }
            }
            catch (ServiceActivationException ex)
            {
                throw new ServiceActivationException(ex.Message);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            // throw new NotImplementedException();
        }

        public int InsertPoInstallment(PurchaseOrderInstallment model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    // model.re = RecordStatus.WaitStatus;
                    model.CreatedBy = createByUserId;
                    model.CreatedWhen = DateTime.Now;
                    context.PurchaseOrderInstallments.Add(model);
                    context.SaveChanges();

                    return model.PoInstallId;
                }
            }
            catch (EntityException ex)
            {
                throw new EntityException(ex.Message);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public void UpdatePoInstallment(PurchaseOrderInstallment model, int updateByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public int DeletePoInstallment(int Id, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.PurchaseOrderInstallments.FirstOrDefault(o => o.PoInstallId == Id);
                    if (modelToDelete == null) return 0;

                    int id = modelToDelete.PoInstallId;
                    // context.Entry(modelToDelete).State = EntityState.Deleted;
                    context.PurchaseOrderInstallments.Remove(modelToDelete);
                    //modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    //modelToDelete.UpdatedBy = deleteByUserId;
                    //modelToDelete.UpdatedWhen = DateTime.Now;                    
                    context.SaveChanges();
                    return id;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public IEnumerable<PurchaseOrderInstallmentItem> SelectPoInstallmentItem(
            PurchaseOrderInstallmentItem filter = null, List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseOrderInstallmentItem> query = context.PurchaseOrderInstallmentItems;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query,
                            (current, includePath) => current.Include(includePath));
                    }

                    if (filter != null)
                    {
                        object[] param;
                        query = query.Where(KPIS.GERP.Models.Class.Utility.GenerateWhereString(filter, out param), param);
                    }

                    var x = query.ToList();
                    return x;
                }
            }
            catch (ServiceActivationException ex)
            {
                throw new ServiceActivationException(ex.Message);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            // throw new NotImplementedException();
        }

        public int InsertPoInstallmentItem(PurchaseOrderInstallmentItem model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    // model.re = RecordStatus.WaitStatus;
                    model.CreatedBy = createByUserId;
                    model.CreatedWhen = DateTime.Now;
                    context.PurchaseOrderInstallmentItems.Add(model);
                    context.SaveChanges();

                    return model.PoInstallId;
                }
            }
            catch (EntityException ex)
            {
                throw new EntityException(ex.Message);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public void UpdatePoInstallmentItem(PurchaseOrderInstallmentItem model, int updateByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public int DeletePoInstallmentItem(int Id, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.PurchaseOrderInstallmentItems.Find(Id);
                    int id = modelToDelete.PoInstallId;
                    if (modelToDelete == null) return 0;

                    // context.Entry(modelToDelete).State = EntityState.Deleted;
                    context.PurchaseOrderInstallmentItems.Remove(modelToDelete);
                    //modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    //modelToDelete.UpdatedBy = deleteByUserId;
                    //modelToDelete.UpdatedWhen = DateTime.Now;                    
                    context.SaveChanges();
                    return id;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new NotImplementedException();
        }

        public string[] ContactPo(int PoId)
        {
            GERPContext context = new GERPContext();
            string ContactName = "";
            string Bankname = "";
            string BranchName = "";
            string ConAddress = "";
            string BankAccName = "";

            var x = (from a in context.PurchaseOrders
                join b in context.Bidders on a.BidderId equals b.BidderId into bs
                from b in bs.DefaultIfEmpty()
                join c in context.MasContacts on b.ConId equals c.ConId into cs
                from c in cs.DefaultIfEmpty()
                join d in context.MasContactBanks on b.ConId equals d.ConId into ds
                from d in ds.DefaultIfEmpty()
                join e in context.MasBankBranchs on d.BranchId equals e.BranchId into es
                from e in es.DefaultIfEmpty()
                join f in context.MasBanks on e.BankId equals f.BankId into fs
                from f in fs.DefaultIfEmpty()
                join j in context.MasBankAccounts on e.BranchId equals j.BranchId into js
                from j in js.DefaultIfEmpty()
                join g in context.PurchaseOrderItems on a.PoId equals g.PoId into gs
                from g in gs.DefaultIfEmpty()
                join h in context.BidderQuotations on g.BidderQuoId equals h.BidderQuoId into hs
                from h in hs.DefaultIfEmpty()
                join k in context.PurchaseOrderInstallmentItems on h.BidderQuoId equals k.BidderQuoId into ks
                from k in ks.DefaultIfEmpty()
                where a.PoId == PoId
                select
                    new
                    {
                        c.NameTh,
                        f.Name,
                        e.BranchName,
                        ConAddress = c.Address + "  " + c.Amphur + "  " + c.Province,
                        BankAccName = j.Name
                    }).FirstOrDefault();

            if (x != null)
            {
                ContactName = x.NameTh;
                Bankname = x.Name;
                BranchName = x.BranchName;
                BankAccName = x.Name;
                ConAddress = x.ConAddress;
            }

            return new string[] {ContactName, Bankname, BranchName, ConAddress, BankAccName};
        }

        public List<string[]> TotalNetAmountPoItem(int PoId)
        {
            GERPContext context = new GERPContext();
            List<string[]> Results = new List<string[]>();

            var x = (from a in context.PurchaseOrders
                join b in context.PurchaseOrderInstallments on a.PoId equals b.PoId into bs
                from b in bs
                join c in context.PurchaseOrderInstallmentItems on b.PoInstallId equals c.PoInstallId into cs
                from c in cs
                where a.PoId == PoId
                group c by new {b.PoInstallId, b.RequireDate, b.InstallNumber}
                into d
                select new
                {
                    d.Key.PoInstallId,
                    d.Key.RequireDate,
                    d.Key.InstallNumber
                    ,
                    SumVatAmount = d.Sum(v => v.VatAmount)
                    ,
                    SumNetAmount = d.Sum(v => v.NetAmount)
                }).ToList();

            foreach (var item in x)
            {
                string[] result = new string[5];
                result[0] = item.PoInstallId.ToString();
                result[1] = (item.RequireDate != null ? item.RequireDate.Value.ToLongDateString() : "");
                result[2] = item.InstallNumber.ToString();
                result[3] = (item.SumVatAmount ?? 0).ToString("#,##0.00");
                result[4] = (item.SumNetAmount ?? 0).ToString("#,##0.00");


                Results.Add(result);
            }

            return Results;
        }

        public string[] CollateralPo(int PoId)
        {
            GERPContext context = new GERPContext();
            string RequireDate = "";
            string RequireDuration = "";
            string ReceiptNo = "";
            string DateStartCount = "";
            string LookUpName = "";
            string Amount = "";
            string PenaltyRate = "";

            var x = (from a in context.PurchaseOrders
                join b in context.Bidders on a.BidderId equals b.BidderId
                join c in context.BidderCollaterals on b.BidderId equals c.BidderId
                join d in context.IcmMasLookUps on c.ColTypeId equals d.LookUpId
                join e in context.PurchaseorderPenalties on a.PoId equals e.PoId
                where a.PoId == PoId && c.ColTypeId == 29
                select
                    new
                    {
                        a.RequireDate,
                        a.RequireDuration,
                        c.ReceiptNo,
                        a.DateStartCount,
                        d.LookUpName,
                        c.Amount,
                        e.PenaltyRate
                    }).FirstOrDefault();

            if (x != null)
            {
                RequireDate = x.RequireDate.ToString();
                RequireDuration = x.RequireDuration.ToString();
                ReceiptNo = x.ReceiptNo;
                DateStartCount = x.DateStartCount.ToString();
                LookUpName = x.LookUpName;
                Amount = x.Amount.ToString();
                PenaltyRate = x.PenaltyRate.ToString();
            }

            return new string[]
            {RequireDate, RequireDuration, ReceiptNo, DateStartCount, LookUpName, Amount, PenaltyRate};
        }

        public string ThaiBaht(string txt)
        {
            string bahtTxt, n, bahtTH = "";
            double amount;
            try
            {
                amount = Convert.ToDouble(txt);
            }
            catch
            {
                amount = 0;
            }
            bahtTxt = amount.ToString("####.00");
            string[] num = {"ศูนย์", "หนึ่ง", "สอง", "สาม", "สี่", "ห้า", "หก", "เจ็ด", "แปด", "เก้า", "สิบ"};
            string[] rank = {"", "สิบ", "ร้อย", "พัน", "หมื่น", "แสน", "ล้าน"};
            string[] temp = bahtTxt.Split('.');
            string intVal = temp[0];
            string decVal = temp[1];
            if (Convert.ToDouble(bahtTxt) == 0)
                bahtTH = "ศูนย์บาทถ้วน";
            else
            {
                for (int i = 0; i < intVal.Length; i++)
                {
                    n = intVal.Substring(i, 1);
                    if (n != "0")
                    {
                        if ((i == (intVal.Length - 1)) && (n == "1"))
                            bahtTH += "เอ็ด";
                        else if ((i == (intVal.Length - 2)) && (n == "2"))
                            bahtTH += "ยี่";
                        else if ((i == (intVal.Length - 2)) && (n == "1"))
                            bahtTH += "";
                        else
                            bahtTH += num[Convert.ToInt32(n)];
                        bahtTH += rank[(intVal.Length - i) - 1];
                    }
                }
                bahtTH += "บาท";
                if (decVal == "00")
                    bahtTH += "ถ้วน";
                else
                {
                    for (int i = 0; i < decVal.Length; i++)
                    {
                        n = decVal.Substring(i, 1);
                        if (n != "0")
                        {
                            if ((i == decVal.Length - 1) && (n == "1"))
                                bahtTH += "เอ็ด";
                            else if ((i == (decVal.Length - 2)) && (n == "2"))
                                bahtTH += "ยี่";
                            else if ((i == (decVal.Length - 2)) && (n == "1"))
                                bahtTH += "";
                            else
                                bahtTH += num[Convert.ToInt32(n)];
                            bahtTH += rank[(decVal.Length - i) - 1];
                        }
                    }
                    bahtTH += "สตางค์";
                }
            }
            return bahtTH;
        }

        public string[] PositionNamePo(int PoId)
        {
            GERPContext context = new GERPContext();
            string name = "";
            string posname = "";
            string PoName = "";
            string OrderDate = "";

            var x = (from a in context.PurchaseOrders
                join b in context.Employees on a.CreatedBy equals b.EmpId into bs
                from b in bs
                join e in context.Positions on b.PosId equals e.PosId into es
                from e in es
                where a.PoId == PoId
                select new {name = b.FirstName + "   " + b.LastName, posname = e.Name, PoName = a.Name, a.OrderDate})
                .FirstOrDefault();

            if (x != null)
            {
                name = x.name;
                posname = x.posname;
                PoName = x.PoName;
                OrderDate = x.OrderDate.Value.ToLongDateString();
            }

            return new string[] {name, posname, PoName, OrderDate};
        }

        public List<Dictionary<string, string>> PoItems(int PoId)
        {
            GERPContext context = new GERPContext();

            var x = (from a in context.PurchaseOrders
                join b in context.PurchaseOrderItems on a.PoId equals b.PoId into Bs
                from b in Bs.DefaultIfEmpty()
                join c in context.BidderQuotations on b.BidderQuoId equals c.BidderQuoId into Cs
                from c in Cs.DefaultIfEmpty()
                join d in context.PurchaseRequestItems on c.PrItemId equals d.PrItemId into Ds
                from d in Ds.DefaultIfEmpty()
                join e in context.MasResourceItems on d.ResItemId equals e.ResItemId into Es
                from e in Es.DefaultIfEmpty()
                join f in context.MasUnits on e.UnitId equals f.UnitId into Fs
                from f in Fs.DefaultIfEmpty()
                where a.PoId == PoId
                select new
                {
                    ResName = e.Name, 
                    UnitName = f.Name, 
                    c.Qty, 
                    c.Price,
                    c.NetAmount,
                    c.ExcludeVatAmount,
                    c.VatAmount
                }).ToList();

            List<Dictionary<string, string>> Dics = new List<Dictionary<string, string>>();
            string A = context.PurchaseOrders.Where(o => o.PoId == PoId).FirstOrDefault().Name.ToString();

            int nIndex = 1;
            foreach (var item in x)
            {
                Dictionary<string, string> dic = new Dictionary<string, string>();
                //decimal SumPrice = (item.Qty ?? 0)*(item.Price ?? 0);
                decimal SumPrice = item.ExcludeVatAmount.Value;
                decimal Vat = (SumPrice*7)/100;
                //decimal ExcludeVatAmount = (SumPrice - Vat);
                decimal ExcludeVatAmount = SumPrice;
                decimal VatAmount = item.VatAmount ?? 0;
                if (item.ResName == null)
                {
                    dic.Add("ResName", A);
                    dic.Add("UnitName", "งานจ้าง");
                }
                else
                {
                    dic.Add("ResName", item.ResName);
                    dic.Add("UnitName", item.UnitName);
                }
                dic.Add("No", nIndex.ToString());
                //dic.Add("ResName", item.ResName);
                //dic.Add("UnitName", item.UnitName);
                dic.Add("Qty", item.Qty.ToString());
                dic.Add("Price", (item.Price??0).ToString("#,##0.00"));
                //dic.Add("SumPrice", ((item.Qty ?? 0) * (item.Price ?? 0)).ToString("#,##0.00"));
                dic.Add("SumPrice", ExcludeVatAmount.ToString("#,##0.00"));
                dic.Add("VatAmount", VatAmount.ToString("#,##0.00"));
                dic.Add("NetAmount", (item.NetAmount ?? 0).ToString("#,##0.00"));

                Dics.Add(dic);
                nIndex++;
            }

            return Dics;
        }

        #endregion [InstallmentItem]
    }
}